#!/bin/sh /etc/rc.common

START=99
APP="firmware"
EXTRA_COMMANDS="echo_lastest_version echo_current_version lastest_version_tmp lastest_version_tmp_get update_now auto_update cron_set configuration_restore"

get_version_data() {
	config_load "$APP"
	config_get version_url config version_url
	[ -z "$version_url" ] && {
		echo "Invalid version URL."
		return 1
	}
	version_data=$(wget -qO - "$version_url" 2>/dev/null)
	[ -z "$version_data" ] && return 1
	return 0
}

get_current_version() {
	file_version_date='/etc/firmware'
	version_build=$(cat '/etc/openwrt_version' 2>/dev/null)
	version_date=$(cat "$file_version_date" 2>/dev/null)
	[ -z "$version_build" ] || [ -z "$version_date" ] || {
		current_version="${version_build}_${version_date}"
		return 0
	}
	return 1
}

get_lastest_version() {
	get_version_data && {
	lastest_version=$(echo -e "$version_data"|head -n 1)
	}
	[ -z "$lastest_version" ] && return 1
	return 0
}

check_update_true() {
	[ -z "$1" ] || [ -z "$2" ] || {
		lastest_version_build=$(echo ${1%%_*}|grep -o '[0-9]\+')
		current_version_build=$(echo ${2%%_*}|grep -o '[0-9]\+')
		if [ $lastest_version_build -gt $current_version_build ]; then
			return 0
		elif [ $lastest_version_build -eq $current_version_build ]; then
			[ ${1##*_} -gt ${2##*_} ] && return 0
		fi
	}
	return 1
}

lastest_version_tmp() {
	rm -f /tmp/firmware_lastest &>/dev/null
	[ -z "$1" ] && return 1
	echo "$1" >"/tmp/firmware_lastest"
	return 0
}

lastest_version_tmp_get() {
	[ -f "/tmp/firmware_lastest" ] && cat "/tmp/firmware_lastest"
	exit 0
}

echo_lastest_version() {
	get_lastest_version && echo "$lastest_version"
}

echo_current_version() {
	get_current_version && echo "$current_version"
}

update_now() {
	[ -z "$1" ] && return 1
	config_load "$APP"
	config_get version_url config version_url
	config_get download_to config download_to '/tmp'
	[ -z "$version_url" ] && {
		echo "Invalid version URL."
		return 1
	}
	update_url="${version_url%/*}/"
	[ -z "$update_url" ] && {
		echo "Invalid version URL."
		return 1
	}
	lastest_version_bin="$update_url$1.bin"
	lastest_version_md5sum=$(wget -qO - "$lastest_version_bin.md5" 2>/dev/null | grep -o '[0-9a-zA-Z]\{32\}')
	download_bin="$download_to/$1.bin"
	[ -z "$lastest_version_md5sum" ] && {
		echo "Failed to get the new firmware's MD5."
		return 1
	}
	[ -f "$download_bin" ] && rm -f "$download_bin"
	wget -O "$download_bin" "$lastest_version_bin"
	[ -f "$download_bin" ] || {
		echo "Failed to download firmware."
		return 1
	}
	download_bin_md5sum=$(md5sum "$download_bin" | grep -o '[0-9a-zA-Z]\{32\}')
	[ -z "$download_bin_md5sum" ] && {
		echo "Could not get downloaded firmware's MD5."
		return 1
	}
	[ "$lastest_version_md5sum" = "$download_bin_md5sum" ] || {
		echo "MD5 check failled."
		rm -f "$download_bin"
		return 1
	}
	mtd_check=$(cat /proc/mtd | grep 'firmware')
	[ -z "$mtd_check" ] && {
		echo "Could not found mtd \"firmware\"."
		rm -f "$download_bin"
		return 1
	}
	mtd -r write "$download_bin" firmware || {
		echo "Failed to flash firmware."
		rm -f "$download_bin"
		return 1
	}
	echo "Firmware updated. Rebooting ..."
	return 0
}

auto_check() {
	lastest_version="$(echo_lastest_version)"
	current_version="$(echo_current_version)"
	check_update_true "$lastest_version" "$current_version" && lastest_version_tmp "$lastest_version"
}

configuration_restore_start() {
	[ -z "$1" ] && {
		echo "No configuration location set."
	}
	restore_script='/tmp/configuration_restore'
	rm -f "$restore_script" &>/dev/null
	if [ "$2" = 'url' ]; then
		wget -qO "$restore_script" "$1" || {
			echo "Failed to download configuration file."
			return 1
		}
	elif [ "$2" = 'path' ]; then
		[ -f "$1" ] || {
			echo "Could not find configuration file."
			return 1
		}
		cp -f "$1" "$restore_script"
	else
		echo "No configuration type set."
		return 1
	fi
	[ -f "$restore_script" ] || {
		echo "Could not find $restore_script."
		return 1
	}
	if ( head -n 1 "$restore_script" | grep "#!/bin/sh" &>/dev/null ); then
		chmod 755 "$restore_script"
		[ -z "$configuration_wifi_ssid" ] && configuration_wifi_ssid='OpenWrt'
		$restore_script restore "$configuration_wifi_ssid" "$configuration_wifi_password"&>/dev/null
		rm -f "$restore_script"
		echo "Done."
		return 0
	else
		echo "Unknown configuration file."
		return 1
	fi
}

configuration_restore() {
	config_load "$APP"
	config_get configuration_location config configuration_location
	config_get configuration_wifi_ssid config configuration_wifi_ssid
	config_get configuration_wifi_password config configuration_wifi_password
	[ -z "$configuration_location" ] && {
		echo "No configuration location set."
		return 1
	}
	configuration_location=$(echo "$configuration_location"|tr -d ' ')
	LOCATION=$(echo "$configuration_location"|grep -Eo 'http(s)?://.*')
	[ -z "$LOCATION" ]||{
		configuration_restore_start "$LOCATION" "url"
		return 0
	}
	LOCATION=$(echo "$configuration_location"|grep -Eo '(/\w+)+')
	[ -z "$LOCATION" ]||{
		configuration_restore_start "$LOCATION" "path"
		return 0
	}
	echo "Invalid configuration location."
	return 1
}

cron_get_option() {
	cron_path='/etc/crontabs'
	cron_bin='/etc/init.d/firmware auto_check'
	USER=$(id -un)
	if [ -z "$USER" ]; then
		cron_file="$cron_path/root"
	else
		cron_file="$cron_path/$USER"
	fi
}

cron_remove() {
	[ -f "$cron_file" ] && {
		line_no=$(cat "$cron_file" | grep -n -x -m 1 "# $APP" | awk -F':' 'NR=1{print $1}')
		[ -z "$line_no" ] || {
			sed -i "$line_no,$(($line_no+1))d" "$cron_file"
			cron_data=$(cat "$cron_file")
			if [ -z "$cron_data" ]; then
				rm -f "$cron_file"
				/etc/init.d/cron stop
			else
				/etc/init.d/cron restart
			fi
		}
	}
}

cron_set() {
	config_load "$APP"
	config_get auto_check config auto_check '0'
	cron_get_option
	[ "$auto_check" = "0" ] && {
		cron_remove
		return 1
	}
	cron_item="$auto_check $cron_bin"
	[ -d "$cron_path" ] || mkdir -p "$cron_path"
	if [ -f "$cron_file" ]; then
		match_true=$(cat $cron_file | grep -n "$cron_bin")
		if [ -z "$match_true" ]; then
			echo -e "# $APP\n$cron_item" >>"$cron_file"
			/etc/init.d/cron restart
		else
			line_no="${match_true%%:*}"
			cron_item=$(echo -e "$cron_item" | sed 's/\//\\\//g')
			[ -z "$line_no" ] || [ -z "$cron_item" ] || {
				sed -i "${line_no}s/^.*$/$cron_item/" "$cron_file"
				/etc/init.d/cron restart
			}
		fi
	else
		echo -e "# $APP\n$cron_item" >"$cron_file"
		/etc/init.d/cron restart
	fi
}

start() {
	cron_set
}

restart() {
	cron_set
}

stop() {
	cron_get_option
	cron_remove
}
